#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

#ifdef WIN32
#   include <windows.h>
#endif

#ifndef WIN32
#   include <dirent.h>
#	define _S_IFREG	S_IFREG
#endif

#include "struc_arg.h"
#include "process.h"
#include "display.h"

#define MAX_SIZE 1024

/**FUNCTION*******************************************/
int startProcessing( arg_t* pArgs )
{
    int result = 0;
    char* strLookouut =  pArgs->firstArg_->paths_;
    pArgs->firstArg_ =  pArgs->firstArg_->next_;

    while( pArgs->firstArg_->next_ )
    {
        if( pArgs->firstArg_->paths_ )
        {
            if( isFile(pArgs->firstArg_->paths_) )
            {
                basicLookout(pArgs->firstArg_->paths_, strLookouut, pArgs->trigger_v , pArgs);
            }
            else
            {
                basicLookoutFolder(pArgs->firstArg_->paths_, strLookouut, pArgs->trigger_v, pArgs->trigger_R, pArgs);
            }
        }
        pArgs->firstArg_ = pArgs->firstArg_->next_;
    }
    return result;
}

/**FUNCTION*******************************************/
int isFile(const char* pFileName)
{
	int ok  = 0;

	struct stat stFileInfo;

	if ( stat(pFileName,&stFileInfo) == 0 )
	{
		ok = (stFileInfo.st_mode & _S_IFREG) != 0 ;
	}

	return ok;
}

/**FUNCTION*******************************************/
void basicLookout(char* pPath, const char* pStr, int pInvert, arg_t* pArgs)
{
    FILE * file = fopen(pPath, "r");
    char* line = malloc(sizeof(char) * MAX_SIZE);
    int lineNumber = 0;
    if (file != NULL)
    {
        while( NULL != fgets(line, MAX_SIZE, file) )
        {
            ++lineNumber;
            //-v, --invert-match sélectionner les lignes sans concordance
            if( !pInvert )
            {
                if( 0 != strstr(line, pStr) )
                {
                    showResult(line, pPath, lineNumber, pArgs);
                    //addMatch(line, pPath, lineNumber, pFirst);
                }
            }
            else
            {
                if( 0 == strstr(line, pStr) )
                {
                    showResult(line, pPath, lineNumber, pArgs);
                    //addMatch(line, pPath, lineNumber, pFirst);
                }
            }
        }
    }
    free(line);
}

/**FUNCTION*******************************************/
void basicLookoutFolder(const char* pPath, const char* pStr, int pInvert, int pRecurs, arg_t* pArgs)
{
#ifdef WIN32
    WIN32_FIND_DATA File;
    HANDLE hSearch;
    char* fold = malloc( (sizeof(pPath) * sizeof(char)) + (4 * sizeof(char)));
    strcat(fold, pPath);
    if( fold[strlen(fold)-1] != '/')
            strcat(fold, "/");
    strcat(fold, "*.*");

    hSearch = FindFirstFile(fold, &File);
    if (hSearch != INVALID_HANDLE_VALUE)
    {
        do {
            char* finPath = malloc( (sizeof( pPath ) * sizeof(char)) + (sizeof(File.cFileName) * sizeof(char)) + sizeof(char) );
                strcat(finPath, pPath);
                if( finPath[strlen(finPath)-1] != '/')
                    strcat(finPath, "/");
                strcat(finPath, File.cFileName);
                basicLookout(finPath, pStr, pFirst, pInvert, pArgs);
                free(finPath);
        } while (FindNextFile(hSearch, &File));

        FindClose(hSearch);
    }
    free(fold);
#else
    DIR * dir = opendir(pPath);
    if (dir != NULL)
    {
        struct dirent * ent;
        while ((ent = readdir(dir)) != NULL )
        {
            if( DT_REG == ent->d_type  )
            {
                char* finPath = malloc( (sizeof( pPath ) * sizeof(char)) + (sizeof(ent->d_name) * sizeof(char)) + sizeof(char) );
                strcpy(finPath, pPath);
                if( finPath[strlen(finPath)-1] != '/')
                    strcat(finPath, "/");
                strcat(finPath, ent->d_name);

                if( isFile(finPath) )
                    basicLookout(finPath, pStr, pInvert, pArgs);

                free(finPath);
            }
            else if( pRecurs && DT_DIR == ent->d_type && NULL == strstr(ent->d_name, ".") && NULL == strstr(ent->d_name, "..") )
            {
                char* finPath = malloc( (sizeof( pPath ) * sizeof(char)) + (sizeof(ent->d_name) * sizeof(char)) + sizeof(char) );
                strcpy(finPath, pPath);

                if( finPath[strlen(finPath)-1] != '/')
                    strcat(finPath, "/");

                strcat(finPath, ent->d_name);

                basicLookoutFolder(finPath, pStr, pInvert, pRecurs, pArgs);
                free(finPath);
            }
        }
        closedir(dir);
    }
#endif
}

/**FUNCTION*******************************************/
void printMessage(const char* pMessage, int pType, const arg_t* pArg_t)
{
    if( !pArg_t->trigger_s )
    {
        switch( pType )
        {
            case MSG_INFO:
                printf("INFO : %s", pMessage);
            break;
            case MSG_WARNING:
                printf("WARNING : %s", pMessage);
            break;
            case MSG_ERROR:
                printf("ERROR : %s", pMessage);
            break;
            default:
            break;
        }
    }
}

/**FUNCTION*******************************************/
void displayResults(const result_t* pFirst, arg_t* pArgs)
{
    if( pFirst )
    {
        int it = 0;
        if( !pArgs->trigger_m)
        {
            it =  1;
        }

        while( pFirst &&  it != pArgs->trigger_m )
        {
            if( pFirst->str_ )
            {
                if( pArgs->trigger_B )
                {
                    displayContextBefore(pArgs->trigger_B, pFirst->fileName_, pFirst->lineNumber_);
                }
                else
                {
                    if( pArgs->trigger_l )
                    {

                    }
                    else if( pArgs->trigger_L )
                    {

                    }
                    else
                    {
                        if( !pArgs->trigger_h )
                        {
                            displayFileName(pFirst);
                        }
                        if( pArgs->trigger_n )
                        {
                            displayLineNumber(pFirst);
                        }
                    }

                    printf("%s", pFirst->str_ );
                }

                ++it;
            }
            pFirst = pFirst->next_;
        }
    }
}

/**FUNCTION*******************************************/
void showResult(char* pLine, char* pPath, int pLineNumber, arg_t* pArgs)
{
    result_t* current = malloc(sizeof(result_t));

    current->str_ = pLine;
    current->fileName_ = pPath;
    current->lineNumber_ = pLineNumber;
    displayResults(current, pArgs);

    free(current);
}
